A code fingerprint, referred to herein also as a fingerprint, is specific processor behavior that occurs when a given section of code is executing. This processor behavior includes any recognizable behavior such as a particular sequence of branch prediction hits and misses, a particular sequence of data cache hits and misses, a particular sequence of taken and not taken branch instructions, and/or any other behavior or pattern recognizable by hardware. Code fingerprints include, but are not limited to: data cache hit miss sequences for various cache levels, data cache hit miss sequences for a given instruction at a given cache level, sequences of correct/incorrect predictions for either a code segment or for a specific set of branches in a code segment, and a branch taken/not taken history when a given instruction is executed. A code fingerprint may also be a sequence of values, including but not limited to: a sequence of branch target addresses, a sequence of indirect branch target addresses, a sequence of addresses loaded by a load instruction either by a specific instruction or by a sequence of instructions, and/or a sequence of call signatures either for a given function or for all functions.
The number of code fingerprints that a given processor can recognize when code is executed in a computing environment is presently limited because different types of hardware are required to recognize different types of behaviors that comprise different code fingerprints. Thus, a given processor may only recognize a limited number of code fingerprints, which can lead to issues. For example, if recognition of a given fingerprint is not supported in a computing environment, the runtime environment has no way of confirming that a certain sequence is executing. Additionally, a fingerprint recognition apparatus may not have the capability of recognizing a new types of fingerprint that today's rapidly-changing technology may require.